package com.situ.shoplook.admin.config;

import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.situ.shoplook.common.model.Account;
import com.situ.shoplook.common.util.JsonResult;
import com.situ.shoplook.common.util.JwtUtils;
import com.situ.shoplook.common.util.WebAppContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.NonNull;
import org.springframework.web.servlet.HandlerInterceptor;

import java.time.Instant;
import java.util.Map;

/**
 * 功能：
 *
 * @author 千堆雪
 * @version 1.0.0
 * <p>
 * created by 千堆雪 on 2024/8/11, last modified by 千堆雪 on 2024/8/11
 */
public class JwtInterceptor implements HandlerInterceptor {
    private static final Logger LOGGER = LoggerFactory.getLogger(JwtInterceptor.class);
    private final String secret;
    private final ObjectMapper objectMapper;

    public JwtInterceptor(String secret, ObjectMapper objectMapper) {
        this.secret = secret;
        this.objectMapper = objectMapper;
    }

    @Override
    public boolean preHandle(HttpServletRequest req, @NonNull HttpServletResponse resp, @NonNull Object handler) throws Exception {
        String token = req.getHeader("Authorization");

        try {
            DecodedJWT jwt = JwtUtils.decode(token, this.secret);

            Map<String, Claim> claims = jwt.getClaims();
            String username = claims.get("username").asString();

            //3.从session或Redis中取出用户数据
            Account account = new Account();
            account.setUsername(username);
            WebAppContext.setCurrentAccount(account);

            //4.过期时间
            Claim claim = claims.get("exp");
            Instant instant = claim.asInstant();

            //token有效期剩余不到5分钟，即将过期
            if (instant.minusMillis(5).isBefore(Instant.now())) {
                //续发token
                String newJwt = JwtUtils.encode(WebAppContext.getCurrentAccount(), 30, secret);
                resp.setHeader("jwt", newJwt);
            }
            return true;

        } catch (Exception e) {
            LOGGER.error("token无效或已过期", e);
            JsonResult<?> result = new JsonResult<>(false, 401, 1401, "token无效或已过期");
            String json = this.objectMapper.writeValueAsString(result);
            WebAppContext.writeJson(resp, json);
            return false;
        }
    }
}
